home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ddj0897.zip / DYN401.ZIP / threads / thread.c < prev    next >
C/C++ Source or Header  |  1997-04-16  |  20KB  |  860 lines

  1.  
  2.  
  3. /*  Copyright (c) 1993-1996 Algorithms Corporation  */
  4. /*  All rights reserved.  */
  5.  
  6.  
  7.  
  8.  
  9. /*  This file automatically generated by dpp - do not edit  */
  10.  
  11. #define    DPP_STRATEGY    2
  12. #define    DPP_FASTWIDE    0
  13.  
  14.  
  15.  
  16. #line 18 "thread.d"
  17. #include <string.h> 
  18.  
  19. #ifndef unix 
  20. #include <conio.h> 
  21. #else 
  22. int getch(void); 
  23. int kbhit(void); 
  24. #endif 
  25.  
  26.  
  27. typedef struct _priority_queue *PQ; 
  28.  
  29. #define    CLASS    Thread_c
  30. #define    ivType    Thread_iv_t
  31.  
  32. #include "generics.h"
  33.  
  34. object    Thread_c;
  35.  
  36.  
  37. #line 38 "thread.c"
  38. typedef struct  _Thread_iv_t  {
  39.     object iObj;
  40.     char * iName;
  41.     int ( * iFun ) ( void * );
  42.     jmp_buf iRtn;
  43.     char * iStack_buf;
  44.     char * iStack_location;
  45.     int iStack_buf_size;
  46.     int iStack_size;
  47.     int iState;
  48.     int iAutoDispose;
  49.     int iPriority;
  50.     void * iArg;
  51.     int iPrev_state;
  52.     int iHold_count;
  53.     int iRtnVal;
  54.     int iWr;
  55.     object iWait;
  56.     struct _Thread_iv_t * iTwait;
  57.     struct _Thread_iv_t * iNext , * iPrev;
  58.     object iSema;
  59. }    Thread_iv_t;
  60.  
  61.  
  62. #line 63 "thread.c"
  63. typedef struct  _Thread_cv_t  {
  64.     char * cTs_stkpos;
  65.     PQ cMpq;
  66.     PQ cCpq;
  67.     ivType * cCt;
  68.     ivType * cTnr;
  69.     ivType * cGkt;
  70.     PQ cFpql;
  71.     object cThreads;
  72.     unsigned long cThrno;
  73. }    Thread_cv_t;
  74.  
  75. static    Thread_cv_t    *Thread_cv;
  76.  
  77.  
  78. #line 76 "thread.d"
  79. struct _priority_queue { 
  80.     int priority; 
  81.     ivType *thread; 
  82.     PQ next; 
  83. }; 
  84.  
  85.  
  86.  
  87. jmp_buf _t_start; 
  88.  
  89.  
  90.  
  91. #define STACKINC 100 
  92.  
  93.  
  94.  
  95. #define NTICKS 1 
  96.  
  97. static objrtn Release(object self, int yld); 
  98.  
  99. #ifdef FUNCTIONS 
  100.  
  101. #define NEXT_THREAD next_thread() 
  102.  
  103. static void next_thread(void); 
  104. static void add_tnr(ivType *t); 
  105. static void del_tnr(ivType *t); 
  106.  
  107. #else 
  108.  
  109. #line 116 "thread.d"
  110. #define NEXT_THREAD if (Thread_cv->cCpq) Thread_cv->cCpq->thread = Thread_cv->cCpq->thread->iNext; if (Thread_cv->cGkt && kbhit()) { Release(Thread_cv->cGkt->iObj, 0); Thread_cv->cGkt = NULL; } if (Thread_cv->cCpq = Thread_cv->cMpq) Thread_cv->cCt = Thread_cv->cCpq->thread; else exit(0) 
  111.  
  112. #line 122 "thread.d"
  113. #define add_tnr(t) if (t->iNext = Thread_cv->cTnr) Thread_cv->cTnr->iPrev = t; t->iPrev = NULL; Thread_cv->cTnr = t 
  114.  
  115. #line 130 "thread.d"
  116. #define del_tnr(t) if (t->iPrev) t->iPrev->iNext = t->iNext; else Thread_cv->cTnr = t->iNext; if (t->iNext) t->iNext->iPrev = t->iPrev 
  117.  
  118. #endif 
  119.  
  120. extern void _start_timer(void); 
  121.  
  122.  
  123. static void start_thread(ivType *s); 
  124. static void stop_thread(ivType *t); 
  125. static void resolve_waits(ivType *t); 
  126. static void delete_wait(ivType *t); 
  127. static PQ new_pq(void); 
  128. static void free_pq(PQ t); 
  129. static void delete_sema_waits(ivType *t); 
  130. static void _dynace_yield(void); 
  131. static char *strsave(char *); 
  132.  
  133. #ifdef FUNCTIONS 
  134.  
  135. static void next_thread(void) 
  136.     if (Thread_cv->cCpq) 
  137.         Thread_cv->cCpq->thread = Thread_cv->cCpq->thread->iNext; 
  138.     if (Thread_cv->cGkt && kbhit()) { 
  139.         Release(Thread_cv->cGkt->iObj, 0); 
  140.         Thread_cv->cGkt = NULL; 
  141.     } 
  142.     if (Thread_cv->cCpq = Thread_cv->cMpq) 
  143.         Thread_cv->cCt = Thread_cv->cCpq->thread; 
  144.     else 
  145.         exit(0); 
  146.  
  147. #endif 
  148.  
  149.  
  150.  
  151.  
  152. static void start_thread(ivType *s) 
  153.     PQ tpq, ppq, npq; 
  154.  
  155.     for (ppq=NULL, tpq=Thread_cv->cMpq ; tpq && s->iPriority < tpq->priority ; ppq=tpq, tpq=tpq->next); 
  156.     if (!tpq || s->iPriority != tpq->priority) { 
  157.         npq = new_pq(); 
  158.         s->iNext = s->iPrev = s; 
  159.         npq->priority = s->iPriority; 
  160.         npq->thread = s; 
  161.         npq->next = tpq; 
  162.         if (ppq) 
  163.             ppq->next = npq; 
  164.         else 
  165.             Thread_cv->cMpq = npq; 
  166.     } else 
  167.         if (tpq == Thread_cv->cCpq) { 
  168.         s->iNext = tpq->thread->iNext; 
  169.         s->iPrev = tpq->thread; 
  170.         tpq->thread->iNext = s; 
  171.         s->iNext->iPrev = s; 
  172.     } else { 
  173.         s->iNext = tpq->thread; 
  174.         s->iPrev = tpq->thread->iPrev; 
  175.         tpq->thread->iPrev = s; 
  176.         s->iPrev->iNext = s; 
  177.         tpq->thread = s; 
  178.     } 
  179.  
  180.  
  181.  
  182. static void stop_thread(ivType *t) 
  183.     PQ pq, ppq; 
  184.  
  185.     for (ppq=NULL, pq=Thread_cv->cMpq ; pq && pq->priority != t->iPriority ; 
  186.     ppq=pq, pq=pq->next); 
  187.     if (!pq) 
  188.         goto error; 
  189.     if (t->iNext != t) { 
  190.         t->iPrev->iNext = t->iNext; 
  191.         t->iNext->iPrev = t->iPrev; 
  192.         if (pq->thread == t) { 
  193.             pq->thread = t->iNext; 
  194.             if (pq == Thread_cv->cCpq) 
  195.                 Thread_cv->cCpq = NULL; 
  196.         } 
  197.     } else { 
  198.         if (pq->thread != t) 
  199.             goto error; 
  200.         if (pq == Thread_cv->cCpq) 
  201.             Thread_cv->cCpq = NULL; 
  202.         if (ppq) 
  203.             ppq->next = pq->next; 
  204.         else 
  205.             Thread_cv->cMpq = pq->next; 
  206.         free_pq(pq); 
  207.     } 
  208.     return; 
  209.     error: 
  210.     fprintf(stderr, "Bad priority queue\n"); 
  211.     exit(1); 
  212.  
  213. #ifdef FUNCTIONS 
  214.  
  215.  
  216.  
  217. static void add_tnr(ivType *t) 
  218.     if (t->iNext = Thread_cv->cTnr) 
  219.         Thread_cv->cTnr->iPrev = t; 
  220.     t->iPrev = NULL; 
  221.     Thread_cv->cTnr = t; 
  222.  
  223.  
  224.  
  225. static void del_tnr(ivType *t) 
  226.     if (t->iPrev) 
  227.         t->iPrev->iNext = t->iNext; 
  228.     else 
  229.         Thread_cv->cTnr = t->iNext; 
  230.     if (t->iNext) 
  231.         t->iNext->iPrev = t->iPrev; 
  232.  
  233. #endif 
  234.  
  235. imeth objrtn Kill(object self, int rtn)
  236. { Thread_iv_t *iv = GetIVs(Thread, self);
  237.     if (iv->iState == DONE_THREAD) 
  238.         return self; 
  239.     INHIBIT_THREADER; 
  240.     iv->iRtnVal = rtn; 
  241.     if (iv->iStack_buf) { 
  242.         free(iv->iStack_buf); 
  243.         iv->iStack_buf = NULL; 
  244.         iv->iStack_buf_size = iv->iStack_size = 0; 
  245.     } 
  246.     if (iv->iState == NEW_THREAD || iv->iState == RUNNING_THREAD) { 
  247.         stop_thread(iv); 
  248.         add_tnr(iv); 
  249.     } else if (iv->iState == WAITING_FOR_THREAD) 
  250.         delete_wait(iv); 
  251.     iv->iState = DONE_THREAD; 
  252.     if (iv->iSema) 
  253.         delete_sema_waits(iv); 
  254.     if (iv->iWait) 
  255.         resolve_waits(iv); 
  256.     if (iv == Thread_cv->cGkt) 
  257.         Thread_cv->cGkt = NULL; 
  258. #if 0 
  259.         if (iKmrp) { 
  260.         static gRemoveRegisteredMemory_t rrm = NULL; 
  261.  
  262.         if (!rrm) 
  263.             rrm = cmcPointer(Dynace, gRemoveRegisteredMemory); 
  264.         (rrm)(Dynace, iKmrp); 
  265.         iKmrp = NULL; 
  266.     } 
  267. #endif 
  268.         ENABLE_THREADER; 
  269.     if (!Thread_cv->cCpq || Thread_cv->cCt == iv) { 
  270.         Thread_cv->cCt = NULL; 
  271.         _dynace_yield(); 
  272.     } 
  273.     return self; 
  274.  
  275. imeth objrtn Dispose(object self)
  276. { Thread_iv_t *iv = GetIVs(Thread, self);
  277.     INHIBIT_THREADER; 
  278.     if (iv->iStack_buf) 
  279.         free(iv->iStack_buf); 
  280.     if (iv->iState == NEW_THREAD || iv->iState == RUNNING_THREAD) 
  281.         stop_thread(iv); 
  282.     else { 
  283.         if (iv->iState == WAITING_FOR_THREAD) 
  284.             delete_wait(iv); 
  285.         del_tnr(iv); 
  286.     } 
  287.  
  288.     iv->iState = DONE_THREAD; 
  289.     if (iv->iSema) 
  290.         delete_sema_waits(iv); 
  291.     if (iv->iWait) { 
  292.         static gDispose_t dispose = NULL; 
  293.  
  294.         if (!dispose) 
  295.             dispose = imcPointer(LinkObject, gDispose); 
  296.         resolve_waits(iv); 
  297.         (*dispose)(iv->iWait); 
  298.     } 
  299.     if (iv == Thread_cv->cGkt) 
  300.         Thread_cv->cGkt = NULL; 
  301. #if 0 
  302.         if (iKmrp) { 
  303.         static gRemoveRegisteredMemory_t rrm = NULL; 
  304.  
  305.         if (!rrm) 
  306.             rrm = cmcPointer(Dynace, gRemoveRegisteredMemory); 
  307.         (*rrm)(Dynace, iKmrp); 
  308.     } 
  309. #endif 
  310.         gRemoveStr(Thread_cv->cThreads, iv->iName); 
  311.     free(iv->iName); 
  312.     oSuper(Thread_c, gDispose, self)(self); 
  313.     ENABLE_THREADER; 
  314.     if (!Thread_cv->cCpq || Thread_cv->cCt == iv) { 
  315.         Thread_cv->cCt = NULL; 
  316.         _dynace_yield(); 
  317.     } 
  318.     return NULL; 
  319.  
  320. static char *strsave(char *s) 
  321.     char *p = Tnalloc(char, strlen(s)+1); 
  322.     strcpy(p, s); 
  323.     return p; 
  324.  
  325. cmeth objrtn Thread_cm_gNew(object self)
  326.     return gShouldNotImplement(self, "gNew"); 
  327.  
  328. cmeth objrtn Thread_cm_gNewThread(object self, char *name, ifun fun, int priority, void *arg, int run, int autoDispose)
  329.     char buf[30]; 
  330.     object obj = oSuper(Thread_c, gNew, self)(self); 
  331.     ivType *iv = ivPtr(obj); 
  332.     static gFindStr_t find = NULL; 
  333.     static gAddStr_t add = NULL; 
  334.  
  335.     INHIBIT_THREADER; 
  336.     iv->iObj = obj; 
  337.     if (name) 
  338.         iv->iName = strsave(name); 
  339.     else { 
  340.         sprintf(buf, "unnamed-%ld", ++Thread_cv->cThrno); 
  341.         iv->iName = strsave(buf); 
  342.     } 
  343.     if (!find) 
  344.         find = imcPointer(StringDictionary, gFindStr); 
  345.     if ((*find)(Thread_cv->cThreads, iv->iName)) { 
  346.         free(iv->iName); 
  347.         oSuper(Thread_c, gDispose, self)(self); 
  348.         ENABLE_THREADER; 
  349.         return NULL; 
  350.     } 
  351.  
  352.     iv->iFun = (int (*)(void *)) fun; 
  353.     iv->iPriority = priority; 
  354.     iv->iArg = arg; 
  355.     iv->iAutoDispose = autoDispose; 
  356.  
  357.     if (!add) 
  358.         add = imcPointer(StringDictionary, gAddStr); 
  359.     (*add)(Thread_cv->cThreads, iv->iName, obj); 
  360.     ENABLE_THREADER; 
  361.  
  362.     if (run) { 
  363.         iv->iState = NEW_THREAD; 
  364.         start_thread(iv); 
  365.         if (Thread_cv->cCt && Thread_cv->cCt->iPriority < priority) 
  366.             _dynace_yield(); 
  367.     } else { 
  368.         iv->iPrev_state = NEW_THREAD; 
  369.         iv->iState = HOLD_THREAD; 
  370.         iv->iHold_count = 1; 
  371.         add_tnr(iv); 
  372.     } 
  373.  
  374.     return obj; 
  375.  
  376. void _start_threader(char *stkpos) 
  377.     object t; 
  378.  
  379.     Thread; 
  380.     if (Thread_cv->cMpq) 
  381.         return; 
  382.  
  383.     INHIBIT_THREADER; 
  384.     t = gNewThread(CLASS, "main", NULL, DEFAULT_PRIORITY, NULL, 1, 0); 
  385.     ENABLE_THREADER; 
  386.     Thread_cv->cCt = ivPtr(t); 
  387.  
  388.     Thread_cv->cCt->iState = RUNNING_THREAD; 
  389.     Thread_cv->cCpq = Thread_cv->cMpq; 
  390.  
  391.     Thread_cv->cTs_stkpos = stkpos; 
  392.  
  393.     _start_timer(); 
  394.  
  395. void _start_thread(void) 
  396.     Thread_cv->cCt->iState = RUNNING_THREAD; 
  397.     _tick_count = NTICKS; 
  398.     Thread_cv->cCt->iRtnVal = (*Thread_cv->cCt->iFun)(Thread_cv->cCt->iArg); 
  399.     Kill(Thread_cv->cCt->iObj, Thread_cv->cCt->iRtnVal); 
  400.     if (Thread_cv->cCt->iAutoDispose) 
  401.         Dispose(Thread_cv->cCt->iObj); 
  402.  
  403. imeth objrtn Hold(object self)
  404. { Thread_iv_t *iv = GetIVs(Thread, self);
  405.     if (iv->iState == DONE_THREAD) 
  406.         return self; 
  407.     if (iv->iState == HOLD_THREAD) { 
  408.         iv->iHold_count++; 
  409.         return self; 
  410.     } 
  411.     if (iv->iState == NEW_THREAD || iv->iState == RUNNING_THREAD) { 
  412.         stop_thread(iv); 
  413.         add_tnr(iv); 
  414.     } 
  415.     iv->iPrev_state = iv->iState; 
  416.     iv->iState = HOLD_THREAD; 
  417.     iv->iHold_count = 1; 
  418.     if (iv == Thread_cv->cCt) 
  419.         _dynace_yield(); 
  420.     return self; 
  421.  
  422. imeth objrtn Release(object self, int yld)
  423. { Thread_iv_t *iv = GetIVs(Thread, self);
  424.     if (iv->iState == HOLD_THREAD && !--iv->iHold_count) { 
  425.         iv->iState = iv->iPrev_state; 
  426.         if (iv->iState == NEW_THREAD || iv->iState == RUNNING_THREAD) { 
  427.             del_tnr(iv); 
  428.             start_thread(iv); 
  429.             if (yld && iv->iPriority > Thread_cv->cCt->iPriority) 
  430.                 _dynace_yield(); 
  431.         } 
  432.     } 
  433.     return self; 
  434.  
  435. static void _dynace_yield(void) 
  436.     ivType *t; 
  437.  
  438.  
  439.  
  440.     if (Thread_cv->cCt && Thread_cv->cCt->iState != DONE_THREAD) { 
  441. #ifdef sparc 
  442.  
  443.         Thread_cv->cCt->iStack_location = (char *) &t - 0x80; 
  444. #else 
  445.         Thread_cv->cCt->iStack_location = (char *) &t; 
  446. #endif 
  447.         if ((Thread_cv->cCt->iStack_size = Thread_cv->cTs_stkpos - Thread_cv->cCt->iStack_location) < 0) 
  448.             Thread_cv->cCt->iStack_size = 0; 
  449.         if (Thread_cv->cCt->iStack_size > Thread_cv->cCt->iStack_buf_size) { 
  450.             Thread_cv->cCt->iStack_buf_size = ((Thread_cv->cCt->iStack_size / STACKINC) + 1) * STACKINC; 
  451.             if (Thread_cv->cCt->iStack_buf) 
  452.                 Thread_cv->cCt->iStack_buf = Tnrealloc(char, Thread_cv->cCt->iStack_buf_size, Thread_cv->cCt->iStack_buf); 
  453.             else 
  454.                 Thread_cv->cCt->iStack_buf = Tnalloc(char, Thread_cv->cCt->iStack_buf_size); 
  455. #if 0 
  456.             { 
  457.                 static gChangeRegisteredMemory_t crm=NULL; 
  458.                 static gRegisterMemory_t rm; 
  459.  
  460.                 if (!crm) { 
  461.                     INHIBIT_THREADER; 
  462.                     crm = cmcPointer(Dynace, gChangeRegisteredMemory); 
  463.                     rm = cmcPointer(Dynace, gRegisterMemory); 
  464.                     ENABLE_THREADER; 
  465.                 } 
  466.                 if (Thread_cv->cCt->iKmrp) 
  467.                     (*crm)(Dynace, Thread_cv->cCt->iKmrp, Thread_cv->cCt->iStack_buf, (long) Thread_cv->cCt->iStack_buf_size); 
  468.                 else 
  469.                     Thread_cv->cCt->iKmrp = (void *)(*rm)(Dynace, Thread_cv->cCt->iStack_buf, (long) Thread_cv->cCt->iStack_buf_size); 
  470.             } 
  471. #endif 
  472.         } 
  473.         if (Thread_cv->cCt->iStack_size) { 
  474. #ifdef sparc 
  475.             asm("t 3"); 
  476. #endif 
  477.             memcpy(Thread_cv->cCt->iStack_buf, Thread_cv->cCt->iStack_location, Thread_cv->cCt->iStack_size); 
  478.         } 
  479.  
  480.  
  481.  
  482.         if (setjmp(Thread_cv->cCt->iRtn)) { 
  483.  
  484.  
  485.  
  486.             if (Thread_cv->cCt->iStack_size) 
  487.                 memcpy(Thread_cv->cCt->iStack_location, Thread_cv->cCt->iStack_buf, Thread_cv->cCt->iStack_size); 
  488.             _tick_count = NTICKS; 
  489.             return; 
  490.         } 
  491.     } 
  492.  
  493.  
  494.  
  495.     NEXT_THREAD; 
  496.  
  497.     if (Thread_cv->cCt->iState == NEW_THREAD) 
  498.         longjmp(_t_start, 1); 
  499.     else { 
  500. #ifdef sparc 
  501.         if (Thread_cv->cCt->iStack_size){ 
  502.             asm("t 3"); 
  503.             memcpy(Thread_cv->cCt->iStack_location, Thread_cv->cCt->iStack_buf, Thread_cv->cCt->iStack_size); 
  504.         } 
  505. #endif 
  506.         longjmp(Thread_cv->cCt->iRtn, 1); 
  507.     } 
  508.  
  509. cmeth objrtn Thread_cm_gFindStr(object self, char *name)
  510.     USE(self); 
  511.     return name ? gFindValueStr(Thread_cv->cThreads, name) : (Thread_cv->cCt ? Thread_cv->cCt->iObj : (object) NULL); 
  512. #if 0 
  513.     ivType *t, *s; 
  514.     PQ pq; 
  515.  
  516.     if (!name) 
  517.         return Thread_cv->cCt ? Thread_cv->cCt->iObj : NULL; 
  518.     for (pq=Thread_cv->cMpq ; pq ; pq=pq->next) { 
  519.         s = t = pq->thread; 
  520.         do { 
  521.             if (t->iName && !strcmp(t->iName, name)) 
  522.                 return t->iObj; 
  523.             t = t->iNext; 
  524.         } while (t != s); 
  525.     } 
  526.     for (t=Thread_cv->cTnr ; t ; t=t->iNext) 
  527.         if (t->iName && !strcmp(t->iName, name)) 
  528.         return t->iObj; 
  529.     return NULL; 
  530. #endif 
  531.  
  532. imeth int Thread_im_gIntValue(object self)
  533. { Thread_iv_t *iv = GetIVs(Thread, self);
  534.     return iv->iRtnVal; 
  535.  
  536. imeth int Thread_im_gState(object self)
  537. { Thread_iv_t *iv = GetIVs(Thread, self);
  538.     return iv->iState; 
  539.  
  540. imeth char * Thread_im_gName(object self)
  541. { Thread_iv_t *iv = GetIVs(Thread, self);
  542.     return iv->iName; 
  543.  
  544. imeth int Thread_im_gPriority(object self)
  545. { Thread_iv_t *iv = GetIVs(Thread, self);
  546.     return iv->iPriority; 
  547.  
  548. imeth objrtn Thread_im_gChangePriority(object self, int p)
  549. { Thread_iv_t *iv = GetIVs(Thread, self);
  550.     int f, oldp; 
  551.  
  552.     oldp = iv->iPriority; 
  553.     if (f = iv->iState == NEW_THREAD || iv->iState == RUNNING_THREAD) 
  554.         stop_thread(iv); 
  555.     iv->iPriority = p; 
  556.     if (f) 
  557.         start_thread(iv); 
  558.     if (Thread_cv->cCt == iv && p < oldp && Thread_cv->cMpq->thread->iPriority > p || 
  559.         Thread_cv->cCt != iv && f && p > Thread_cv->cCt->iPriority) 
  560.         _dynace_yield(); 
  561.     return self; 
  562.  
  563. imeth int Thread_im_gWaitFor(object self)
  564. { Thread_iv_t *iv = GetIVs(Thread, self);
  565.     if (iv == Thread_cv->cCt) 
  566.         return 0; 
  567.     if (iv->iState != DONE_THREAD) { 
  568.         stop_thread(Thread_cv->cCt); 
  569.         add_tnr(Thread_cv->cCt); 
  570.  
  571.         INHIBIT_THREADER; 
  572.         if (!iv->iWait) 
  573.             iv->iWait = gNew(LinkObject); 
  574.         gAddFirst(iv->iWait, Thread_cv->cCt->iObj); 
  575.         ENABLE_THREADER; 
  576.  
  577.         Thread_cv->cCt->iTwait = iv; 
  578.         Thread_cv->cCt->iState = WAITING_FOR_THREAD; 
  579.         _dynace_yield(); 
  580.         return Thread_cv->cCt->iWr; 
  581.     } else 
  582.         return iv->iRtnVal; 
  583.  
  584.  
  585.  
  586. static void resolve_waits(ivType *t) 
  587.     object thread; 
  588.     static gFirst_t first=NULL; 
  589.     static gDisposeFirst_t disposeFirst; 
  590.  
  591.     if (!t->iWait) 
  592.         return; 
  593.     INHIBIT_THREADER; 
  594.     if (!first) { 
  595.         first = imcPointer(LinkObject, gFirst); 
  596.         disposeFirst = imcPointer(LinkObject, gDisposeFirst); 
  597.     } 
  598.     while (thread = (*first)(t->iWait)) { 
  599.         ivType *tt; 
  600.  
  601.         tt = ivPtr(thread); 
  602.         tt->iState = RUNNING_THREAD; 
  603.         del_tnr(tt); 
  604.         start_thread(tt); 
  605.         tt->iWr = t->iRtnVal; 
  606.         t->iTwait = NULL; 
  607.         (*disposeFirst)(t->iWait); 
  608.     } 
  609.     ENABLE_THREADER; 
  610.  
  611.  
  612.  
  613.  
  614. static void delete_wait(ivType *t) 
  615.     object linkSequence, linkValue, thread; 
  616.     static gDispose_t disposeNode, dispose; 
  617.     static gValue_t value; 
  618.     static gNext_t next; 
  619.     static gSequenceLinks_t sequenceLinks = NULL; 
  620.  
  621.     if (!t->iTwait->iWait) 
  622.         return; 
  623.     INHIBIT_THREADER; 
  624.     if (!sequenceLinks) { 
  625.         sequenceLinks = imcPointer(LinkObject, gSequenceLinks); 
  626.         next = imcPointer(LinkSequence, gNext); 
  627.         value = imcPointer(LinkValue, gValue); 
  628.         disposeNode = imcPointer(LinkValue, gDispose); 
  629.         dispose = imcPointer(LinkSequence, gDispose); 
  630.     } 
  631.     linkSequence = (*sequenceLinks)(t->iTwait->iWait); 
  632.     while (linkValue = (*next)(linkSequence)) { 
  633.         thread = (*value)(linkValue); 
  634.         if (thread == t->iObj) { 
  635.             (*disposeNode)(linkValue); 
  636.             break; 
  637.         } 
  638.     } 
  639.     if (linkValue) 
  640.         (*dispose)(linkSequence); 
  641.     ENABLE_THREADER; 
  642.  
  643. static PQ new_pq(void) 
  644.     PQ t; 
  645.  
  646.     if (Thread_cv->cFpql) { 
  647.         t = Thread_cv->cFpql; 
  648.         Thread_cv->cFpql = t->next; 
  649.         memset(t, 0, sizeof(*t)); 
  650.     } else 
  651.         t = Tcalloc(struct _priority_queue); 
  652.     return(t); 
  653.  
  654. static void free_pq(PQ t) 
  655.     t->next = Thread_cv->cFpql; 
  656.     Thread_cv->cFpql = t; 
  657.  
  658. static void delete_sema_waits(ivType *t) 
  659.     static gRemoveWaits_t removeWaits = NULL; 
  660.  
  661.     INHIBIT_THREADER; 
  662.     if (!removeWaits) 
  663.         removeWaits = imiPointer(t->iSema, gRemoveWaits); 
  664.     (*removeWaits)(t->iSema, t->iObj); 
  665.     t->iSema = NULL; 
  666.     ENABLE_THREADER; 
  667.  
  668. cmeth int Thread_cm_gBlockingGetkey(object self)
  669.     USE(self); 
  670.     if (Thread_cv->cGkt) 
  671.         return -1; 
  672.     if (!kbhit()) { 
  673.         Thread_cv->cGkt = Thread_cv->cCt; 
  674.         Hold(Thread_cv->cCt->iObj); 
  675.     } 
  676.     return getch(); 
  677.  
  678.  
  679.  
  680. imeth objrtn Thread_im_gReleaseSemaphore(object self)
  681. { Thread_iv_t *iv = GetIVs(Thread, self);
  682.     if (iv->iState == WAITING_FOR_SEMAPHORE) { 
  683.         iv->iState = RUNNING_THREAD; 
  684.         del_tnr(iv); 
  685.         start_thread(iv); 
  686.     } else if (iv->iState == HOLD_THREAD && iv->iPrev_state == WAITING_FOR_SEMAPHORE) 
  687.         iv->iPrev_state = RUNNING_THREAD; 
  688.     iv->iSema = NULL; 
  689.     return self; 
  690.  
  691.  
  692.  
  693. imeth objrtn Thread_im_gWaitSemaphore(object self, object sema)
  694. { Thread_iv_t *iv = GetIVs(Thread, self);
  695.     stop_thread(iv); 
  696.     add_tnr(iv); 
  697.     iv->iState = WAITING_FOR_SEMAPHORE; 
  698.     iv->iSema = sema; 
  699.     return self; 
  700.  
  701. static objrtn MarkThreadStacks(object self) 
  702.     ivType *t, *s; 
  703.     PQ pq; 
  704.     static gMarkRange_t markRange = NULL; 
  705.  
  706.     if (!markRange) 
  707.         markRange = cmcPointer(Dynace, gMarkRange); 
  708.  
  709.     for (pq=Thread_cv->cMpq ; pq ; pq=pq->next) { 
  710.         s = t = pq->thread; 
  711.         do { 
  712.             if (t->iStack_buf && t->iStack_size) 
  713.                 (*markRange)(Dynace, (char _HUGE **)t->iStack_buf, (char _HUGE **)(t->iStack_buf + t->iStack_size)); 
  714.             t = t->iNext; 
  715.         } while (t != s); 
  716.     } 
  717.     for (t=Thread_cv->cTnr ; t ; t=t->iNext) 
  718.         if (t->iStack_buf && t->iStack_size) 
  719.         (*markRange)(Dynace, (char _HUGE **) t->iStack_buf, (char _HUGE **)(t->iStack_buf + t->iStack_size)); 
  720.     return self; 
  721.  
  722. #ifdef unix 
  723.  
  724.  
  725.  
  726. int kbhit(void) 
  727.     return 0; 
  728.  
  729. int getch(void) 
  730.     return getchar(); 
  731.  
  732. #endif 
  733.  
  734. imeth objrtn Thread_im_gCopy(object self)
  735.     return gShouldNotImplement(self, "Copy/DeepCopy"); 
  736.  
  737. static void init_class(void) 
  738.  
  739.  
  740.  
  741.     __dynace_yield = _dynace_yield; 
  742.  
  743.     Thread_cv->cThreads = gNewWithInt(StringDictionary, 41); 
  744.  
  745.     gMarkingMethod(CLASS, (ofun) MarkThreadStacks); 
  746.  
  747. #line 806 "thread.c"
  748.  
  749. objrtn    Thread_initialize(void)
  750. {
  751.     static  CRITICALSECTION  cs;
  752.     static  int volatile once = 0;
  753.  
  754.     ENTERCRITICALSECTION(_CI_CS_);
  755.     if (!once) {
  756.         INITIALIZECRITICALSECTION(cs);
  757.         once = 1;
  758.     }
  759.     LEAVECRITICALSECTION(_CI_CS_);
  760.  
  761.     ENTERCRITICALSECTION(cs);
  762.  
  763.     if (Thread_c) {
  764.         LEAVECRITICALSECTION(cs);
  765.         return Thread_c;
  766.     }
  767.     INHIBIT_THREADER;
  768.     Thread_c = gNewClass(Class, "Thread", sizeof(Thread_iv_t), sizeof(Thread_cv_t), END);
  769.     cMethodFor(Thread, gNewThread, Thread_cm_gNewThread);
  770.     cMethodFor(Thread, gFindStr, Thread_cm_gFindStr);
  771.     cMethodFor(Thread, gBlockingGetkey, Thread_cm_gBlockingGetkey);
  772.     cMethodFor(Thread, gNew, Thread_cm_gNew);
  773.     iMethodFor(Thread, gChangePriority, Thread_im_gChangePriority);
  774.     iMethodFor(Thread, gIntValue, Thread_im_gIntValue);
  775.     iMethodFor(Thread, gState, Thread_im_gState);
  776.     iMethodFor(Thread, gWaitSemaphore, Thread_im_gWaitSemaphore);
  777.     iMethodFor(Thread, gPriority, Thread_im_gPriority);
  778.     iMethodFor(Thread, gHold, Hold);
  779.     iMethodFor(Thread, gRelease, Release);
  780.     iMethodFor(Thread, gDispose, Dispose);
  781.     iMethodFor(Thread, gName, Thread_im_gName);
  782.     iMethodFor(Thread, gKill, Kill);
  783.     iMethodFor(Thread, gReleaseSemaphore, Thread_im_gReleaseSemaphore);
  784.     iMethodFor(Thread, gCopy, Thread_im_gCopy);
  785.     iMethodFor(Thread, gDeepDispose, Dispose);
  786.     iMethodFor(Thread, gDeepCopy, Thread_im_gCopy);
  787.     iMethodFor(Thread, gWaitFor, Thread_im_gWaitFor);
  788.  
  789.     Thread_cv = GetCVs(Thread);
  790.  
  791.     init_class();
  792.  
  793.     ENABLE_THREADER;
  794.  
  795.     LEAVECRITICALSECTION(cs);
  796.  
  797.     return Thread_c;
  798. }
  799.  
  800.  
  801.  
  802.